# /lab_booking/routers/auth.py

from datetime import timedelta
from typing import Optional

from fastapi import APIRouter, Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer
from jose import JWTError, jwt
from sqlalchemy.orm import Session
from datetime import datetime

from lab_booking import crud, models, schemas
from lab_booking.database import get_db
from lab_booking.config import settings
from lab_booking.utils.wechat_auth import get_openid_from_wechat

# 创建一个独立的路由器实例
router = APIRouter(
    tags=["认证 (Authentication)"] # 为这个模块下的所有 API 添加标签
)

# OAuth2 方案，FastAPI 会用它来在 /docs 中生成授权按钮
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/auth/login") # tokenUrl指向我们的登录接口

# --- TOKEN 相关函数 ---
def create_access_token(data: dict, expires_delta: Optional[timedelta] = None):
    """根据用户信息创建 JWT Token"""
    to_encode = data.copy()
    if expires_delta:
        expire = datetime.utcnow() + expires_delta
    else:
        expire = datetime.utcnow() + timedelta(minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES)
    to_encode.update({"exp": expire})
    encoded_jwt = jwt.encode(to_encode, settings.SECRET_KEY, algorithm=settings.ALGORITHM)
    return encoded_jwt


# --- 登录接口 ---
@router.post("/login", response_model=schemas.Token)
def login_for_access_token(user_info: schemas.UserLogin, db: Session = Depends(get_db)):
    """
    微信小程序登录接口。
    接收前端的 code 和用户信息，返回 JWT Token。
    """
    # 1. 用 code 换取 openid
    openid = get_openid_from_wechat(user_info.code)
    
    # 2. 根据 openid 查找或创建/更新用户
    user = crud.create_or_update_user(db, user_info=user_info, openid=openid)
    
    # 3. 创建 JWT Token，将 user.id 作为 token 的主题 (subject)
    access_token = create_access_token(data={"sub": str(user.id)})
    
    return {"access_token": access_token, "token_type": "bearer"}


# --- 依赖项：获取当前用户 ---
def get_current_user(token: str = Depends(oauth2_scheme), db: Session = Depends(get_db)) -> models.User:
    """
    一个 FastAPI 依赖项，用于保护需要登录才能访问的接口。
    它会解析请求头中的 Token，验证它，并返回对应的数据库用户模型。
    如果验证失败，会自动抛出 HTTP 异常。
    """
    credentials_exception = HTTPException(
        status_code=status.HTTP_401_UNAUTHORIZED,
        detail="Could not validate credentials",
        headers={"WWW-Authenticate": "Bearer"},
    )
    try:
        payload = jwt.decode(token, settings.SECRET_KEY, algorithms=[settings.ALGORITHM])
        user_id_str: str = payload.get("sub") # 从 payload 获取字符串类型的 user_id
        if user_id_str is None:
            raise credentials_exception
    except JWTError:
        raise credentials_exception
    
    user = db.query(models.User).filter(models.User.id == int(user_id_str)).first()
    if user is None:
        # 如果在这里依然找不到用户，说明 token 可能是伪造的，或者对应的用户已被删除
        raise credentials_exception
    return user